<template>
  <div class="flex flex-col h-screen fill-width-height position-relative">
    <!-- 优化布局的文件上传控件 -->
    <div v-if="allowFileUpload" class="file-upload-container">
      <label class="file-upload-label" :class="{ 'is-dragover': isDragover }">
        <input
          type="file"
          class="file-upload-input"
          @change="handleFileSelect"
          @dragover.prevent="handleDragOver"
          @dragleave.prevent="handleDragLeave"
          @drop.prevent="handleDrop"
          accept="image/jpeg, image/png, image/webp"
        >
        <div class="upload-icon">
          <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
            <path d="M12 5V19" stroke="currentColor" stroke-width="2" stroke-linecap="round"/>
            <path d="M5 12L12 5L19 12" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
          </svg>
        </div>
        <div class="upload-text">
          <p class="upload-main-text">{{ localPanorama ? localPanorama.name : '选择本地全景图' }}</p>
          <p class="upload-sub-text" v-if="!localPanorama">支持JPG、PNG、WebP格式</p>
        </div>
      </label>

      <button v-if="localPanorama" @click="clearSelectedFile" class="clear-upload">清除</button>
    </div>

    <!-- 全景图渲染区域 -->
    <div class="panorama-container relative flex-1 bg-gray-900 overflow-hidden flex-col position-relative min-height-0">
      <div ref="panoramaContainer" class="flex-1"></div>

      <!-- 加载指示器 -->
      <div v-if="isLoading" class="absolute inset-0 flex items-center justify-center bg-black/50 z-20">
        <div class="flex flex-col items-center">
          <div class="w-16 h-16 border-4 border-primary border-t-transparent rounded-full animate-spin"></div>
          <p class="mt-4 text-white text-lg">加载全景图中...</p>
        </div>
      </div>

      <!-- 错误提示 -->
      <div v-if="hasError" class="absolute inset-0 flex items-center justify-center bg-black/70 z-20 p-4">
        <div class="bg-gray-800 text-white p-6 rounded-lg max-w-md">
          <h3 class="text-xl font-bold mb-2 text-red-400">加载失败</h3>
          <p class="mb-4">{{ errorMessage }}</p>
          <button
            @click="retryLoad"
            class="bg-primary hover:bg-primary/80 text-white px-4 py-2 rounded-md transition-colors"
          >
            重试
          </button>
        </div>
      </div>

      <!-- 控制面板 - 调整z-index和样式确保可见 -->
      <div class="controls-panel flex-row height-38 fixed bottom-6 left-1/2 transform -translate-x-1/2 bg-dark/80 backdrop-blur-md text-white px-6 py-3 rounded-full flex items-center gap-6 z-30 transition-all duration-300 shadow-lg">
        <el-button class="control-btn" @click="resetView" title="重置视角">
          <i class="fa fa-refresh"></i>重置视角
        </el-button>
        <el-button class="control-btn" @click="zoomIn" title="放大">
          <i class="fa fa-search-plus"></i>放大
        </el-button>
        <el-button  class="control-btn" @click="zoomOut" title="缩小">
          <i class="fa fa-search-minus"></i>缩小
        </el-button>
        <el-button  class="control-btn" @click="toggleRotation" title="自动旋转">
          <i :class="autoRotate ? 'fa fa-pause' : 'fa fa-play'"></i>自动旋转
        </el-button>
        <el-button  class="control-btn" @click="switchImageSource" title="切换图片源" :disabled="!canSwitchSource">
          <i class="fa fa-exchange" :class="!canSwitchSource ? 'opacity-50' : ''"></i>切换图片源
        </el-button>
        <el-button  class="control-btn" @click="toggleFullscreen" title="全屏查看" :disabled="!canSwitchSource">
          <i :class="isFullscreen ? 'fa fa-compress' : 'fa fa-expand'"></i>全屏
        </el-button>
      </div>

      <!-- 当前图片源指示器 -->
      <div class="absolute top-6 left-6 bg-dark/80 backdrop-blur-md text-white px-4 py-2 rounded-full text-sm z-30">
        <span>{{ currentSource === 'local' ? '本地图片' : '远程图片' }}</span>
      </div>
    </div>

    <!-- 提示信息 -->
    <div v-if="showTutorial" class="bg-dark/80 text-white p-3 text-sm z-20 backdrop-blur-md">
      <div class="container mx-auto flex justify-between items-center">
        <p>
          <i class="fa fa-info-circle mr-1 text-primary"></i>
          提示: 拖拽鼠标旋转视角，使用滚轮缩放，点击按钮切换图片源
        </p>
        <button @click="showTutorial = false" class="text-gray-300 hover:text-white">
          <i class="fa fa-times"></i>
        </button>
      </div>
    </div>
  </div>
</template>

<script>
import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls.js';

export default {
  name: 'PanoramaViewer',
  props: {
    // HTTP全景图地址
    httpPanorama: {
      type: String,
      default: 'https://picsum.photos/id/1018/2000/1000'
    },
    allowFileUpload: {
      type: Boolean,
      default: true
    },
  },
  data() {
    return {
      isDragover: false,
      // 本地全景图文件
      localPanorama: null,

      // Three.js相关对象
      scene: null,
      camera: null,
      renderer: null,
      controls: null,
      sphere: null,
      textureLoader: null,

      // 状态管理
      isLoading: false,
      hasError: false,
      errorMessage: '',
      autoRotate: false,
      isFullscreen: false,
      currentSource: 'http', // 默认使用http源
      showTutorial: true,    // 显示使用提示

      // 容器引用
      container: null,
      animationId: null
    };
  },
  computed: {
    // 是否可以切换图片源
    canSwitchSource() {
      return this.currentSource === 'http' ? !!this.localPanorama : true;
    }
  },
  watch: {
    localPanorama(newVal) {
      // 当本地文件变化且当前源是本地时，重新加载
      if (newVal && this.currentSource === 'local') {
        this.loadPanorama('local');
      }
    },
    httpPanorama(newVal) {
      // 当远程URL变化且当前源是远程时，重新加载
      if (newVal && this.currentSource === 'http') {
        this.loadPanorama('http');
      }
    }
  },
  mounted() {
    this.container = this.$refs.panoramaContainer;
    this.initThreeJs();

    // 监听窗口大小变化
    window.addEventListener('resize', this.onWindowResize);

    // 监听全屏状态变化
    document.addEventListener('fullscreenchange', this.handleFullscreenChange);
    document.addEventListener('webkitfullscreenchange', this.handleFullscreenChange);
    document.addEventListener('mozfullscreenchange', this.handleFullscreenChange);
    document.addEventListener('msfullscreenchange', this.handleFullscreenChange);

    // 5秒后自动隐藏提示信息
    setTimeout(() => {
      this.showTutorial = false;
    }, 5000);
  },
  beforeUnmount() {
    // 清理资源
    window.removeEventListener('resize', this.onWindowResize);
    document.removeEventListener('fullscreenchange', this.handleFullscreenChange);
    document.removeEventListener('webkitfullscreenchange', this.handleFullscreenChange);
    document.removeEventListener('mozfullscreenchange', this.handleFullscreenChange);
    document.removeEventListener('msfullscreenchange', this.handleFullscreenChange);

    if (this.renderer) {
      this.renderer.dispose();
    }

    if (this.controls) {
      this.controls.dispose();
    }

    // 停止动画循环
    if (this.animationId) {
      cancelAnimationFrame(this.animationId);
    }
  },
  methods: {
    // 初始化Three.js场景
    initThreeJs() {
      // 创建场景
      this.scene = new THREE.Scene();

      // 创建相机
      this.camera = new THREE.PerspectiveCamera(
        75,
        this.container.clientWidth / this.container.clientHeight,
        0.1,
        1000
      );
      this.camera.position.set(0, 0, 0.1); // 相机放在球中心

      // 创建渲染器
      this.renderer = new THREE.WebGLRenderer({ antialias: true });
      this.renderer.setSize(this.container.clientWidth, this.container.clientHeight);
      this.renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2)); // 限制像素比以提高性能
      this.container.appendChild(this.renderer.domElement);

      // 创建控制器
      this.controls = new OrbitControls(this.camera, this.renderer.domElement);
      this.controls.enableZoom = true;
      this.controls.enablePan = false;
      this.controls.rotateSpeed = 0.5;
      this.controls.zoomSpeed = 0.7;
      this.controls.enableDamping = true;
      this.controls.dampingFactor = 0.05;

      // 初始化纹理加载器
      this.textureLoader = new THREE.TextureLoader();

      // 开始加载全景图
      this.loadPanorama(this.currentSource);

      // 开始动画循环
      this.animate();
    },

    // 处理文件选择
    handleFileSelect(event) {
      const file = event.target.files[0];
      if (!file) return;

      // 验证文件类型
      const validTypes = ['image/jpeg', 'image/png', 'image/webp'];
      if (!validTypes.includes(file.type)) {
        alert('请选择有效的图片文件 (JPG, PNG 或 WebP)');
        return;
      }

      // 验证文件大小 (最大10MB)
      if (file.size > 10 * 1024 * 1024) {
        alert('图片文件过大，请选择小于10MB的图片');
        return;
      }

      // 验证图片比例 (接近2:1)
      const img = new Image();
      img.onload = () => {
        const aspectRatio = img.width / img.height;
        if (aspectRatio < 1.8 || aspectRatio > 2.2) {
          if (!confirm('全景图最佳比例为2:1，当前图片比例不符，可能影响显示效果，是否继续？')) {
            // 清除选择
            event.target.value = '';
            return;
          }
        }

        // 保存文件并加载
        this.localPanorama = file;
        this.currentSource = 'local';
        this.loadPanorama('local');

        // 重置文件输入，允许重复选择同一文件
        event.target.value = '';
      };
      img.src = URL.createObjectURL(file);
    },

    // 加载全景图
    loadPanorama(source) {
      if (!this.scene) return;

      this.isLoading = true;
      this.hasError = false;
      this.currentSource = source;

      let imageUrl = null;

      // 根据源类型获取图片URL
      if (source === 'local' && this.localPanorama) {
        imageUrl = URL.createObjectURL(this.localPanorama);
      } else if (source === 'http' && this.httpPanorama) {
        imageUrl = this.httpPanorama;
      } else {
        this.isLoading = false;
        this.hasError = true;
        this.errorMessage = source === 'local' ? '未提供有效的本地全景图' : '未提供有效的HTTP全景图地址';
        return;
      }

      // 移除旧的球体
      if (this.sphere) {
        this.scene.remove(this.sphere);
        this.sphere.geometry.dispose();
        if (this.sphere.material.map) {
          this.sphere.material.map.dispose();
        }
        this.sphere.material.dispose();
        this.sphere = null;
      }

      // 加载纹理并创建球体
      this.textureLoader.load(
        imageUrl,
        (texture) => {
          // 创建球体几何体 (半径大一些以便用户感觉在内部)
          const geometry = new THREE.SphereGeometry(500, 60, 40);

          // 反转球体的UV坐标，使纹理贴在内部
          geometry.scale(-1, 1, 1);

          // 创建材质
          const material = new THREE.MeshBasicMaterial({
            map: texture
          });

          // 创建球体网格并添加到场景
          this.sphere = new THREE.Mesh(geometry, material);
          this.scene.add(this.sphere);

          this.isLoading = false;

          // 如果是本地文件，释放URL对象
          if (source === 'local') {
            URL.revokeObjectURL(imageUrl);
          }
        },
        (xhr) => {
          console.log(`加载进度: ${(xhr.loaded / xhr.total) * 100}%`);
        },
        (error) => {
          console.error('加载全景图时出错:', error);
          this.isLoading = false;
          this.hasError = true;
          this.errorMessage = `加载全景图失败: ${error.message || '未知错误'}`;

          // 如果是本地文件，释放URL对象
          if (source === 'local') {
            URL.revokeObjectURL(imageUrl);
          }
        }
      );
    },

    // 窗口大小改变时调整
    onWindowResize() {
      if (!this.camera || !this.renderer || !this.container) return;

      this.camera.aspect = this.container.clientWidth / this.container.clientHeight;
      this.camera.updateProjectionMatrix();
      this.renderer.setSize(this.container.clientWidth, this.container.clientHeight);
    },

    // 动画循环
    animate() {
      this.animationId = requestAnimationFrame(() => this.animate());

      if (this.controls) {
        this.controls.update(); // 更新控制器
      }

      if (this.renderer && this.scene && this.camera) {
        this.renderer.render(this.scene, this.camera); // 渲染场景
      }
    },

    // 重置视角
    resetView() {
      if (this.camera) {
        this.camera.position.set(0, 0, 0.1);
      }
      if (this.controls) {
        this.controls.reset();
      }
    },

    // 放大
    zoomIn() {
      if (this.camera) {
        this.camera.fov = Math.max(30, this.camera.fov - 5);
        this.camera.updateProjectionMatrix();
      }
    },

    // 缩小
    zoomOut() {
      if (this.camera) {
        this.camera.fov = Math.min(120, this.camera.fov + 5);
        this.camera.updateProjectionMatrix();
      }
    },

    // 切换自动旋转
    toggleRotation() {
      this.autoRotate = !this.autoRotate;
      if (this.controls) {
        this.controls.autoRotate = this.autoRotate;
        this.controls.autoRotateSpeed = 1.0;
      }
    },

    // 切换图片源
    switchImageSource() {
      if (!this.canSwitchSource) return;

      const newSource = this.currentSource === 'local' ? 'http' : 'local';
      this.loadPanorama(newSource);
    },

    // 切换全屏
    toggleFullscreen() {
      if (!document.fullscreenElement) {
        this.container.requestFullscreen().catch(err => {
          console.error(`全屏切换错误: ${err.message}`);
          alert(`无法进入全屏模式: ${err.message}`);
        });
      } else {
        if (document.exitFullscreen) {
          document.exitFullscreen();
        }
      }
    },

    // 处理全屏状态变化
    handleFullscreenChange() {
      this.isFullscreen = !!document.fullscreenElement;
    },

    // 重试加载
    retryLoad() {
      this.loadPanorama(this.currentSource);
    },
    // 新增拖拽处理方法
    handleDragOver() {
      this.isDragover = true;
    },
    handleDragLeave() {
      this.isDragover = false;
    },
    handleDrop(event) {
      this.isDragover = false;
      const file = event.dataTransfer.files[0];
      if (file) {
        this.validateAndLoadFile(file); // 复用文件验证逻辑
      }
    },

    // 重构文件选择逻辑（统一处理点击和拖拽的文件）
    // handleFileSelect(event) {
    //   const file = event.target.files[0];
    //   if (file) {
    //     this.validateAndLoadFile(file);
    //     // 重置input值，允许重复选择同一文件
    //     event.target.value = '';
    //   }
    // },

    // 提取文件验证和加载逻辑为单独方法
    validateAndLoadFile(file) {
      // 验证文件类型
      const validTypes = ['image/jpeg', 'image/png', 'image/webp'];
      if (!validTypes.includes(file.type)) {
        alert('请选择有效的图片文件 (JPG, PNG 或 WebP)');
        return;
      }

      // 验证文件大小 (最大10MB)
      if (file.size > 10 * 1024 * 1024) {
        alert('图片文件过大，请选择小于10MB的图片');
        return;
      }

      // 验证图片比例 (接近2:1)
      const img = new Image();
      img.onload = () => {
        const aspectRatio = img.width / img.height;
        if (aspectRatio < 1.8 || aspectRatio > 2.2) {
          if (!confirm('全景图最佳比例为2:1，当前图片比例不符，可能影响显示效果，是否继续？')) {
            return;
          }
        }

        // 保存文件并加载
        this.localPanorama = file;
        this.currentSource = 'local';
        this.loadPanorama('local');
      };
      img.src = URL.createObjectURL(file);
    },

    // 新增清除选中文件方法
    clearSelectedFile() {
      this.localPanorama = null;
      // 重置input值
      const input = this.$el.querySelector('.file-upload-input');
      if (input) input.value = '';
    },
  }
};
</script>

<style scoped>
.panorama-container {
  @apply relative flex-1 overflow-hidden bg-gray-900;
}

/* 控制面板优化 - 确保可见性 */
.controls-panel {
  @apply fixed bottom-6 left-1/2 transform -translate-x-1/2 bg-dark/90 backdrop-blur-md text-white px-6 py-3 rounded-full flex items-center gap-6 z-30 transition-all duration-300 shadow-lg hover:bg-dark/95;
  border: 1px solid rgba(255, 255, 255, 0.2);
}

.control-btn {
  @apply w-10 h-10 rounded-full bg-white/10 hover:bg-primary/80 flex items-center justify-center cursor-pointer transition-all duration-300 relative overflow-hidden;
}

.control-btn::after {
  content: '';
  @apply absolute inset-0 bg-white/10 scale-0 rounded-full transition-transform duration-300;
}

.control-btn:hover::after {
  @apply scale-100;
}

.control-btn:active {
  @apply transform scale-90;
}

/* 全屏按钮优化 - 确保可见性 */
.fullscreen-btn {
  @apply fixed top-6 right-6 w-12 h-12 rounded-full bg-primary/80 backdrop-blur-md text-white flex items-center justify-center cursor-pointer transition-all duration-300 hover:bg-primary z-30 shadow-lg border border-white/10;
}

.fullscreen-btn:active {
  @apply transform scale-90;
}

/* 当前图片源指示器 */
.absolute.top-6.left-6 {
  @apply shadow-lg border border-white/10 transition-all duration-300 hover:bg-dark/95;
}

/* 文件上传容器样式 */
.file-upload-container {
  position: absolute;
  top: 20px;
  right: 10px; /* 靠右放置，避免遮挡中心内容 */
  z-index: 5;
  display: flex;
  align-items: center;
  gap: 10px;
  width: auto;

}

.file-upload-label {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 16px;
  background-color: rgba(255, 255, 255, 0.95);
  border: 2px dashed #ccd6e0;
  border-radius: 10px;
  cursor: pointer;
  transition: all 0.3s ease;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  white-space: nowrap;
}

.file-upload-label.is-dragover {
  border-color: #4287f5;
  background-color: rgba(66, 135, 245, 0.05);
}

.file-upload-input {
  display: none;
}

.upload-icon {
  color: #4287f5;
  flex-shrink: 0;
}

.upload-text {
  text-align: left;
  overflow: hidden;
  text-overflow: ellipsis;
}

.upload-main-text {
  margin: 0 0 2px 0;
  font-weight: 500;
  color: #2d3748;
  font-size: 13px;
  overflow: hidden;
  text-overflow: ellipsis;
}

.upload-sub-text {
  margin: 0;
  font-size: 11px;
  color: #718096;
}

.clear-upload {
  padding: 5px 10px;
  background-color: #f7fafc;
  border: 1px solid #e2e8f0;
  border-radius: 6px;
  font-size: 12px;
  color: #4a5568;
  cursor: pointer;
  transition: all 0.2s ease;
}

.clear-upload:hover {
  background-color: #edf2f7;
  color: #2d3748;
}
</style>
